'use strict';

const authConst = require('../constant/auth-const');
const Service = require('egg').Service;

class RoleAuthService extends Service {

    async getAllAuthApiSrv() {
        const { app } = this;
        return await app.model.ApiAuth.findAll();
    }

    async getBindRoleApiSrv(roleId) {
        const { ctx } = this;

        const queryString =
            `select
                aa.*
                from tbl_role_authority ra
                left join tbl_api_authority aa
                on ra.auth_id = aa.id
                where true
                and ra.role_id = ?
                and ra.type = ?`;

        const paramsData = [roleId, authConst.authType.apiAuth.value];
        return await ctx.helper.sqlQuery(queryString, paramsData);
    }

    async getUnbindRoleApiSrv(roleId) {
        const { ctx } = this;

        const queryString =
            `select * from tbl_api_authority
                where true
                and id not in (select auth_id from tbl_role_authority where role_id = ? and type = ?)`;

        const paramsData = [roleId, authConst.authType.apiAuth.value];
        return await ctx.helper.sqlQuery(queryString, paramsData);
    }

    async getBindRoleRouterSrv(roleId, routerType, parentId) {
        const { ctx } = this;

        let queryString =
            `select rta.* from tbl_role_authority ra
                left join tbl_router_authority rta
                on ra.auth_id = rta.id
                where true
                and ra.role_id = ?
                and ra.type = ?
                and rta.type = ?`;

        const paramsData = [roleId, authConst.authType.routerAuth.value, routerType];
        if (routerType === authConst.authType.twoLevelRouter.value && parentId) {
            queryString += ` and rta.parent_id = ?`;
            paramsData.push(parentId);
        }

        return await ctx.helper.sqlQuery(queryString, paramsData);
    }

    async getUnbindRoleRouterSrv(roleId, routerType, parentId) {
        const { ctx } = this;

        let queryString =
            `select * from tbl_router_authority
             where true
             and id not in (select auth_id from tbl_role_authority where role_id = ? and type = ?)
             and type = ?`;

        const paramsData = [roleId, authConst.authType.routerAuth.value, routerType];
        if (routerType === authConst.authType.twoLevelRouter.value && parentId) {
            queryString += ` and parent_id = ?`;
            paramsData.push(parentId);
        }

        return await ctx.helper.sqlQuery(queryString, paramsData);
    }

    /*async bindRoleRouterSrv(roleId, routerType, authArray, parentId) {
        const { app } = this;

        let queryData =
            `select
                rta.id
                from tbl_role_authority ra
                left join tbl_router_authority rta
                on ra.auth_id = rta.id
                where true
                and ra.role_id = ?
                and ra.type = ?
                and rta.type = ?`;

        const paramData = [roleId, authConst.authType.routerAuth.value, routerType];
        if (routerType === authConst.authType.twoLevelRouter.value && parentId) {
            queryData += ` and rta.parent_id = ?`;
            paramData.push(parentId);
        }

        const queryDelete =
            `delete from tbl_role_authority
                where true
                and auth_id in (select id from (${queryData}) as sr)
                and type = ?`;

        paramData.push(authConst.authType.routerAuth.value);

        const delResult = await app.mysql.query(queryDelete, paramData);

        let bindArray = [];
        if (authArray && authArray.length > 0) {
            bindArray = await app.model.RoleAuth.bulkCreate(authArray);
        }

        return bindArray;
    }*/

    async bindRoleRouterSrv(roleId, routerType, authArray, parentId) {
        const { app, ctx } = this;

        let queryString =
            `select
                ra.id, ra.auth_id, ra.role_id, ra.type, rta.type as routerType
                from tbl_role_authority ra
                left join tbl_router_authority rta
                on ra.auth_id = rta.id
                where true
                and ra.role_id = ?
                and ra.type = ?
                and rta.type = ?`;

        const paramsData = [roleId, authConst.authType.routerAuth.value, routerType];
        if (routerType === authConst.authType.twoLevelRouter.value && parentId) {
            queryString += ` and rta.parent_id = ?`;
            paramsData.push(parentId);
        }

        const roleAuthResult = await ctx.helper.sqlQuery(queryString, paramsData);

        for (const itemResult of roleAuthResult) {
            const result = authArray.some(({auth_id, role_id, type}) => (
                itemResult.role_id === role_id && itemResult.auth_id === auth_id && itemResult.type === type
            ));

            if (!result) {
                await app.model.RoleAuth.destroy({
                    where: {
                        id: itemResult.id
                    }
                });
            }
        }

        for (const authItem of authArray) {
            const { auth_id, role_id, type } = authItem;
            const itemResult = await app.model.RoleAuth.findOne({
                where: {
                    auth_id,
                    role_id,
                    type
                }
            });

            if (!itemResult) {
                await app.model.RoleAuth.create({
                    auth_id,
                    role_id,
                    type
                });
            }
        }

        return await app.model.RoleAuth.findAll({
            where: {
                role_id: roleId,
                type: authConst.authType.routerAuth.value
            }
        });
    }

    async unbindRoleRouterSrv(authId) {
        const { app } = this;

        return await app.model.RoleAuth.destroy({
            where: {
                id: authId
            }
        });
    }

    async getAllAuthRouterSrv() {
        const { ctx } = this;

        const queryParent = `select * from tbl_router_authority where type = ?`;
        const paramParent = [authConst.authType.apiAuth.value];
        const parentRouters = await ctx.helper.sqlQuery(queryParent, paramParent);

        if (parentRouters.length > 0) {
            for (const item of parentRouters) {
                const { id } = item;
                const queryChild = `select * from tbl_router_authority where type = ? and parent_id = ?`;
                const paramChild = [authConst.authType.routerAuth.value, id];
                item.children = await ctx.helper.sqlQuery(queryChild, paramChild);
            }
        }

        return parentRouters;
    }

    async getRoleAuthRouterSrv(roleId) {
        const { ctx } = this;

        const queryParent =
                `select rta.* from tbl_role_authority ra
                    left join tbl_router_authority rta
                    on ra.auth_id = rta.id
                    where true
                    and ra.role_id = ?
                    and ra.type = ?
                    and rta.type = ?`;

        const paramParent = [roleId, authConst.authType.routerAuth.value, authConst.authType.oneLevelRouter.value];
        const parentRouters = await ctx.helper.sqlQuery(queryParent, paramParent);

        if (parentRouters.length > 0) {
            const queryChild =
                `select * from tbl_role_authority ra
                    left join tbl_router_authority rta
                    on ra.auth_id = rta.id
                    where true
                    and ra.role_id = ?
                    and ra.type = ?
                    and rta.parent_id = ?
                    and rta.type = ?`;

            for (const item of parentRouters) {
                const paramChild = [roleId, authConst.authType.routerAuth.value, item.id, authConst.authType.twoLevelRouter.value];
                item.children = await ctx.helper.sqlQuery(queryChild, paramChild);
            }
        }

        return parentRouters;
    }
}

module.exports = RoleAuthService;
